﻿using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;

namespace Niusys.Repostories
{
    public interface ISessionManager
    {
        void AddConfiguration(string configName);
        Configuration GetConfiguration(string configName);
        ISession OpenSession(string key = "");
        IStatelessSession OpenStatelessSession(string key = "");
        string GenerateDbSql(bool isRun);
    }

    public class SessionManager : ISessionManager
    {
        public static bool IsSessionFactoryInited = false;
        public static object initLocker = new object();
        protected readonly Dictionary<string, NHibernate.Cfg.Configuration> _configurations;
        protected readonly Dictionary<string, ISessionFactory> _sessionFactorys;

        public SessionManager()
        {
            _configurations = new Dictionary<string, NHibernate.Cfg.Configuration>();
            _sessionFactorys = new Dictionary<string, ISessionFactory>();
        }

        public void AddConfiguration(string configName)
        {
            if (!_configurations.ContainsKey(configName))
                _configurations.Add(configName, new Configuration().ApplicationConfigurationConfigure(configName));
        }

        /// <summary>
        /// 返回给定configName的configuration
        /// </summary>
        /// <param name="configName"></param>
        /// <returns>如果存在则返回configuration, 不存在返回null</returns>
        public Configuration GetConfiguration(string configName)
        {
            //SessionFactoryInitRequired();
            return _configurations.ContainsKey(configName) ? _configurations[configName] : null;
        }

        public ISession OpenSession(string configName)
        {
            SessionFactoryInitRequired();
            ISession session = (string.IsNullOrWhiteSpace(configName) ? _sessionFactorys.Values.First() : _sessionFactorys[configName]).OpenSession();
            return session;
        }

        public IStatelessSession OpenStatelessSession(string configName)
        {
            SessionFactoryInitRequired();
            return (string.IsNullOrWhiteSpace(configName) ? _sessionFactorys.Values.First() : _sessionFactorys[configName]).OpenStatelessSession();
        }

        public string GenerateDbSql(bool isRun)
        {
            var sbSql = new StringBuilder();
            foreach (var cfg in _configurations)
            {
                var configuration = cfg.Value;
                string conn = configuration.GetProperty("connection.connection_string");
                var connBuilder = new SqlConnectionStringBuilder(conn);
                string databaseName = connBuilder.InitialCatalog;

                sbSql.AppendLine(string.Format(
                    "---------------------------  {0}  ------------------------------------", databaseName));
                sbSql.AppendLine(string.Format("--Name:{0}", cfg.Key));
                sbSql.AppendLine(string.Format("use {0} ", databaseName));
                sbSql.AppendLine("go");

                new SchemaUpdate(configuration).Execute(action =>
                {
                    if (!action.Contains("foreign key"))
                        sbSql.AppendLine(action);
                }, isRun);
            }
            return sbSql.ToString();
        }

        private void SessionFactoryInitRequired()
        {
            if (IsSessionFactoryInited)
                return;
            lock (initLocker)
            {
                if (IsSessionFactoryInited)
                    return;
                foreach (var item in _configurations)
                {
                    _sessionFactorys.Add(item.Key, item.Value.BuildSessionFactory());
                }
                IsSessionFactoryInited = true;
            }
        }
    }
}
